package com.demo.controller;

import com.demo.model.Student;
import com.demo.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;

import javax.annotation.Resource;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 86187
 * Date: 2023-03-13
 * Time: 17:51
 */

@Controller
public class StudentController {
    // 如何获取 StudentService 对象??
    // 1. 使用属性注入的方式.
    // 属性注入的缺点: (1). 功能性问题: 无法注入一个不可变(final)对象.
    //              (2). 通用性问题: 只能适用于 IoC 容器.
    //              (3). 设计原则问题: 更容易违背单一设计原则.
    @Autowired
    private StudentService studentService1;
    // 属性注入的缺点一:  private final StudentService studentService;

    public void sayHi() {
        // 调用 Service 方法. 如何获取呢?
        this.studentService1.sayHi();
    }




    // 2. setter 注入
    // 优点: 更加符合单一设计原则
    // 缺点: (1). 不能注入不可变对象.
    //      (2). 注入对象可被修改.
    private StudentService studentService2;

    @Autowired
    public void setStudentService2(StudentService studentService2) {
        this.studentService2 = studentService2;
    }
    public void sayHello() {
        studentService2.sayHi();
    }



    // 3. 构造方法注入[推荐使用]
    // 优点: (1). 可以注入不可变对象.
    //      (2). 注入对象不会被修改
    //      (3). 完全初始化.
    //      (4). 通用性更好.
    private final StudentService studentService3;

    // 如果只有一个构造方法, @Autowired 可以省略.
    @Autowired
    public StudentController(StudentService studentService, Student student) {
        this.studentService3 = studentService;
    }

    public void toSayHi() {
        studentService3.sayHi();
    }

    // 同⼀类型多个 @Bean 报错
    // 此处 StudentBeans 将两个 Student 对象放到了 Spring 中, 在此处注入时,
    // 如果该变量的名字与 @Bean 注解的方法名不相同, @Resource 可通过 name 属性设置.
    @Resource(name = "getStudentBeans")
    private Student s;

    public void say1() {
        System.out.println(s.toString());
    }

    @Resource
    private Student student;  // 此处的名字和 @Bean 注解的方法名一致, 就不需要用到 name属性了
    public void say2() {
        System.out.println(student.toString());

    }

    @Autowired // 此处的名字和 @Bean 注解的方法名不一致, @Autowired 注解没有name属性, 改造怎么办呢??
    @Qualifier("getStudentBeans") // 使用 @Qualifier 注解, 有筛选作用
    private Student stu;
    public void say3() {
        System.out.println(student.toString());

    }



}
